using Indiefreaks.AceOnSteroids.Entities;
using Indiefreaks.AceOnSteroids.Logic;
using Indiefreaks.Xna.Core;
using Indiefreaks.Xna.Rendering;
using Indiefreaks.Xna.Rendering.Camera;
using Indiefreaks.Xna.Sessions;
using Microsoft.Xna.Framework;

namespace Indiefreaks.AceOnSteroids
{
    /// <summary>
    /// The GameplayGameState will be responsible of initializing, updating and rendering our game session
    /// </summary>
    public class GameplayGameState : GameState
    {
        private AsteroidFactory _asteroidFactory;

        /// <summary>
        /// Creates a new instance
        /// </summary>
        /// <param name="name"/>
        /// <param name="application"/>
        public GameplayGameState(string name, Application application) : base(name, application)
        {
        }

        #region Overrides of GameState

        public override void Initialize()
        {
            // In order to render SunBurn SceneObject instances, we need to add a SunBurn Layer (this isn't required if you're not using SunBurn rendering like in the
            // main menu or introduction)
            AddLayer(new SunBurnLayer(this));

            // we add a basic lighting setup so that we can see something in the scene
            SunBurn.LightManager.SubmitStaticAmbientLight(Color.White.ToVector3(), 0.25f);

            // we create a Free 3D camera so we can navigate within the scene and view the spaceship in multiple angles
            // we keep the Free 3D camera code for potential debug sessions in the future.
            // SunBurn.GetManager<CameraManager>(true).Submit(new FreeCamera3D(Application.GraphicsDevice.Viewport.AspectRatio, 1.0f, 0.1f, 1000f));

            // we change the default camera to a top-down camera to show the game level scene as expected on an Asteroids clone
            var camera = new TargetCamera3D(Application.GraphicsDevice.Viewport.AspectRatio, 1.0f, 0.1f, 10000f)
                             {
                                 Position = new Vector3(0f, 1000f, -10f),
                                 // we set the camera position really high and slightly behind the spaceship Z position to give the 3D feeling
                                 TargetPosition = Vector3.Zero,
                                 // we center the camera view on the world origin
                                 SceneEnvironment = // each camera in IGF contains a SceneEnvironment instance that will be used to control the SunBurn rendering
                                     {
                                         Gravity = 0f,
                                         // since we are in space, we don't want any gravity to be applied on our physic entities.
                                         FogStartDistance = 3000f,
                                         FogEndDistance = 10000f,
                                         // we set the fog start and end distance to something that will allow us to show the scene even at 1500 meters
                                     }
                             };
            // we don't forget to add our camera to the CameraManager
            SunBurn.GetManager<CameraManager>(true).Submit(camera);

            // we now create our Player instance in our GameState using the SessionManager which will automatically register the PlayerAgent for processing.
            // the CreatePlayerAgent has a generic signature to allow you to create your own PlayerAgent
            var player = SessionManager.CurrentSession.CreatePlayerAgent<Player>(SessionManager.CurrentSession.LocalPlayers[0]);

            // we create our asteroid factory and ask the GameState to load its content
            _asteroidFactory = new AsteroidFactory();
            PreLoad(_asteroidFactory);

            // on loading completion, we add the spaceship to the ObjectManager
            LoadingCompleted += delegate
                                    {
                                        SunBurn.ObjectManager.Submit(player.SpaceShip);
                                    };
        }

        #endregion

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            // for the sake of easy illustration, we'll use an input event to add asteroids to the scene
            if (Application.Input.PlayerOne.Buttons.A.IsPressed)
                _asteroidFactory.Create();
        }
    }
}